package com.white.hot.controller.wx;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import com.white.hot.dto.resp.WXPayResp;

public class WXPayUtils
{

	/**
	 * sign签名
	 * 
	 * @param characterEncoding
	 *            编码格式
	 * @param parameters
	 *            请求参数
	 * @param API_KEY
	 *            //API密钥，在商户平台设置
	 * @return
	 */
	public static String createSign(String characterEncoding,SortedMap<Object, Object> parameters, String API_KEY)
	{
		StringBuffer sb = new StringBuffer();
		Set<Entry<Object, Object>> es = parameters.entrySet();
		Iterator<Entry<Object, Object>> it = es.iterator();
		while (it.hasNext())
		{
			Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) it.next();
			String k = (String) entry.getKey();
			Object v = entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k))
			{
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + API_KEY);
		String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding)
				.toUpperCase();
		return sign;
	}

	/**
	 * 将请求参数转换为xml格式的string
	 * 
	 * @param parameters
	 *            请求参数
	 * @return
	 */
	public static String getRequestXml(SortedMap<Object, Object> parameters)
	{
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		Set<Entry<Object, Object>> es = parameters.entrySet();
		Iterator<Entry<Object, Object>> it = es.iterator();
		while (it.hasNext())
		{
			Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k))
			{
				sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
			} else
			{
				sb.append("<" + k + ">" + v + "</" + k + ">");
			}
		}
		sb.append("</xml>");
		return sb.toString();
	}

	/**
	 * 发送https请求
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return 返回微信服务器响应的信息
	 */
	public static String httpsRequest(String requestUrl, String requestMethod,
			String outputStr)
	{
		try
		{
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = new TrustManager[]
			{ new X509TrustManager()
			{

				@Override
				public void checkClientTrusted(
						java.security.cert.X509Certificate[] chain,
						String authType)
						throws java.security.cert.CertificateException
				{
				}

				@Override
				public void checkServerTrusted(
						java.security.cert.X509Certificate[] chain,
						String authType)
						throws java.security.cert.CertificateException
				{
				}

				@Override
				public java.security.cert.X509Certificate[] getAcceptedIssuers()
				{
					return null;
				}

			} };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			conn.setRequestMethod(requestMethod);
			conn.setRequestProperty("content-type","application/x-www-form-urlencoded");
			// 当outputStr不为null时向输出流写数据
			if (null != outputStr)
			{
				OutputStream outputStream = conn.getOutputStream();
				// 注意编码格式
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			// 从输入流读取返回内容
			InputStream inputStream = conn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			StringBuffer buffer = new StringBuffer();
			while ((str = bufferedReader.readLine()) != null)
			{
				buffer.append(str);
			}
			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			conn.disconnect();
			return buffer.toString();
		} catch (ConnectException ce)
		{
			System.out.println("连接超时：{}" + ce.toString());
		} catch (Exception e)
		{
			System.out.println("https请求异常：{}" + e.toString());
		}
		return null;
	}

	/***
	 * 微信预支付订单的解析(xml)
	 * 
	 * @param content
	 * @return
	 */
	public static WXPayResp decodeXml(String content)
	{
		SAXBuilder builder = new SAXBuilder();
		WXPayResp resp = new WXPayResp();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		InputStreamReader reader = null;
		try
		{
			byte[] sbyte = content.getBytes("UTF-8");
			baos.write(sbyte);
			baos.flush();
			ByteArrayInputStream bais = new ByteArrayInputStream(sbyte);
			reader = new InputStreamReader(bais, "UTF-8");
			Document doc = builder.build(reader);
			Element root = doc.getRootElement();

			Element return_code = root.getChild("return_code");
			String rcode = return_code.getValue();
			Element return_msg = root.getChild("return_msg");
			String rmsg = return_msg.getValue();
			if (return_code.equals("FAIL"))
			{
				resp.setResult_code(rcode);
				resp.setResult_msg(rmsg);
				return resp;
			}
			Element appid = root.getChild("appid");
			Element mch_id = root.getChild("mch_id");
			Element nonce_str = root.getChild("nonce_str");
			Element sign = root.getChild("sign");
			Element prepay_id = root.getChild("prepay_id");
			
			resp.setResult_code(rcode);
			resp.setResult_msg(rmsg);
			resp.setAppid(appid.getValue());
			resp.setMch_id(mch_id.getValue());
			resp.setNonce_str(nonce_str.getValue());
			resp.setSign(sign.getValue());
			resp.setPrepay_id(prepay_id.getValue());
			return resp;
		} catch (Exception e)
		{
			return null;
		} finally
		{
			try
			{
				if (reader != null)
				{
					reader.close();
				}
				if (baos != null)
				{
					baos.close();
				}
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
	}
}
